package com.net.xpay.core.service.impl.safePay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayDataBillAccountbookereceiptQueryModel;
import com.alipay.api.domain.AlipayDataBillEreceiptagentApplyModel;
import com.alipay.api.response.AlipayDataBillAccountbookereceiptQueryResponse;
import com.alipay.api.response.AlipayDataBillEreceiptagentApplyResponse;
import com.google.common.base.Preconditions;
import com.net.xpay.common.domain.SafePayOrderReceipt;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.enums.safePay.ApplyReceiptStatus;
import com.net.xpay.common.manager.SafePayOrderReceiptManager;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.service.safePay.SafePayReceiptService;
import com.net.common.exception.BusinessException;
import com.net.common.util.SerializationUtil;
import com.net.xpay.alipay.safePay.PoseidonSafePayAlipayClient;
import com.net.xpay.core.domain.safePay.SafePayOrder;
import com.net.xpay.core.enums.SafePayOrderStatus;
import com.net.xpay.core.manager.safePay.SafePayOrderManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Slf4j
@Service
public class SafePayReceiptServiceImpl implements SafePayReceiptService {

    @Autowired
    private PoseidonSafePayAlipayClient xpaySafePayAlipayClient;

    @Autowired
    private SafePayOrderReceiptManager safePayOrderReceiptManager;

    @Autowired
    private SafePayOrderManager safePayOrderManager;

    @Override
    public SafePayOrderReceipt applySafePayOrderBillFile(User user, Long safePayOrderId) {
        log.info("applySafePayOrderBillFile userId={}|safePayOrderId={}", user.getId(), safePayOrderId);

        SafePayOrder order = safePayOrderManager.findById(user.getId(), safePayOrderId);

        if (order.getStatus() != SafePayOrderStatus.SUCCESS) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "当前转账未成功无法下载回单");
        }
        if (order.getPayFundOrderId() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "无法下载回单");
        }
        //查询一下是否已经在处理中了
        SafePayOrderReceipt selectedReceipt = safePayOrderReceiptManager.findBySafePayOrderId(order.getUserId(), order.getId());
        if (selectedReceipt != null) {
           return reApplySafePayOrderBillFile(selectedReceipt);
        } else {
            return doApplySafePayOrderBillFile(order);
        }
    }

    @Override
    public SafePayOrderReceipt updateReceiptFile(Long id) {
        Preconditions.checkArgument(id != null);

        SafePayOrderReceipt receipt = safePayOrderReceiptManager.getById(id);

        if (receipt.getStatus() != ApplyReceiptStatus.INIT) {
            return receipt;
        }
        AlipayDataBillAccountbookereceiptQueryModel model = new AlipayDataBillAccountbookereceiptQueryModel();
        model.setFileId(receipt.getFileId());
        model.setAgreementNo(receipt.getAgreementNo());

        try {
            AlipayDataBillAccountbookereceiptQueryResponse resp = xpaySafePayAlipayClient.queryAlipayDataBill(model);
            log.info("updateReceiptFile resp={}|id={}", SerializationUtil.obj2String(resp), id);
            if (!resp.isSuccess()) {
                log.info("updateReceiptFile fail id={}|error={}", id, resp.getCode() + "|" + resp.getSubCode() + "|" + resp.getMsg() + "|" + resp.getSubMsg());
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "查询失败:" + resp.getMsg() + "|" + resp.getSubMsg());
            }

            if (resp.getStatus().equals(ApplyReceiptStatus.SUCCESS.getValue())) {
                //成功了
                receipt.setStatus(ApplyReceiptStatus.SUCCESS);
                if (!resp.getDownloadUrl().startsWith("https")) {
                    receipt.setDownloadUrl(resp.getDownloadUrl().replace("http", "https"));
                } else {
                    receipt.setDownloadUrl(resp.getDownloadUrl());
                }

                receipt.setEndTime(LocalDateTime.now());
            } else if (resp.getStatus().equals(ApplyReceiptStatus.FAIL.getValue())) {
                receipt.setStatus(ApplyReceiptStatus.FAIL);
                receipt.setErrorMessage(resp.getErrorMessage());
                receipt.setEndTime(LocalDateTime.now());
            } else {
                //5分账后再查询
                receipt.setQueryCount(receipt.getQueryCount() + 1);
                receipt.setNextQueryTime(LocalDateTime.now().plusMinutes(5L));
                if (receipt.getLastApplyTime().plusDays(2L).isBefore(LocalDateTime.now())) {
                    receipt.setStatus(ApplyReceiptStatus.FAIL);
                    receipt.setErrorMessage("文件生成超时");
                }
            }
            safePayOrderReceiptManager.update(receipt);
            return receipt;
        } catch (AlipayApiException e) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "支付宝接口异常");
        }
    }

    private SafePayOrderReceipt doApplySafePayOrderBillFile(SafePayOrder order) {
        AlipayDataBillEreceiptagentApplyModel applyModel = new AlipayDataBillEreceiptagentApplyModel();
        applyModel.setKey(order.getPayFundOrderId());
        applyModel.setAgreementNo(order.getAgreementNo());
        AlipayDataBillEreceiptagentApplyResponse resp;
        try {
            resp = xpaySafePayAlipayClient.applyAlipayDataBill(applyModel);
            if (!resp.isSuccess() || resp.getFileId() == null) {
                log.warn("doApplySafePayOrderBillFile failed userId={}|id={}|msg={}|subMsg={}|code={}|subCode={}", order.getUserId(), order.getId(), resp.getMsg(), resp.getSubMsg(), resp.getCode(), resp.getSubCode());
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "申请回单失败：" + resp.getMsg() + "|" + resp.getSubMsg());
            }
        } catch (AlipayApiException e) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "系统繁忙，请稍后再试");
        }

        SafePayOrderReceipt receipt = new SafePayOrderReceipt();
        receipt.setUserId(order.getUserId());
        receipt.setSafePayOrderId(order.getId());
        receipt.setAgreementNo(order.getAgreementNo());
        receipt.setPayFundOrderId(order.getPayFundOrderId());
        receipt.setFileId(resp.getFileId());
        receipt.setLastApplyTime(LocalDateTime.now());
        receipt.setStatus(ApplyReceiptStatus.INIT);
        receipt.setNextQueryTime(LocalDateTime.now());
        receipt.setQueryCount(0);

        safePayOrderReceiptManager.save(receipt);

        return receipt;
    }

    private SafePayOrderReceipt reApplySafePayOrderBillFile(SafePayOrderReceipt selectedReceipt) {
        if (selectedReceipt.getStatus() == ApplyReceiptStatus.INIT || selectedReceipt.getStatus() == ApplyReceiptStatus.PROCESS) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "回单已申请，正在处理中");
        }
        AlipayDataBillEreceiptagentApplyModel applyModel = new AlipayDataBillEreceiptagentApplyModel();
        applyModel.setKey(selectedReceipt.getPayFundOrderId());
        applyModel.setAgreementNo(selectedReceipt.getAgreementNo());
        AlipayDataBillEreceiptagentApplyResponse resp;
        try {
            resp = xpaySafePayAlipayClient.applyAlipayDataBill(applyModel);
            if (!resp.isSuccess() || resp.getFileId() == null) {
                log.warn("reApplySafePayOrderBillFile failed userId={}|id={}|msg={}|subMsg={}|code={}|subCode={}", selectedReceipt.getUserId(), selectedReceipt.getId(), resp.getMsg(), resp.getSubMsg(), resp.getCode(), resp.getSubCode());
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "申请回单失败：" + resp.getMsg() + "|" + resp.getSubMsg());
            }
        } catch (AlipayApiException e) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "系统繁忙，请稍后再试");
        }
        selectedReceipt.setFileId(resp.getFileId());
        selectedReceipt.setLastApplyTime(LocalDateTime.now());
        selectedReceipt.setStatus(ApplyReceiptStatus.INIT);
        selectedReceipt.setEndTime(null);
        selectedReceipt.setNextQueryTime(LocalDateTime.now());
        selectedReceipt.setQueryCount(0);

        safePayOrderReceiptManager.update(selectedReceipt);
        return selectedReceipt;
    }
}
